package com.jiexin.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.jiexin.beans.LogType;
import com.jiexin.common.RequestHolder;
import com.jiexin.dao.*;
import com.jiexin.model.SysLogWithBLOBs;
import com.jiexin.model.SysRole;
import com.jiexin.model.SysRoleAcl;
import com.jiexin.model.SysUser;
import com.jiexin.util.IpUtil;
import com.jiexin.util.JsonMapper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: Jay_Liu
 * @Description:
 * @Date: Created in 17:59 2018/4/26 0026
 * @Modified By:
 */
@Service
public class SysRoleAclService {

    @Resource
    SysRoleAclMapper sysRoleAclMapper;

    @Resource
    SysRoleMapper sysRoleMapper;

    @Resource
    SysRoleUserMapper sysRoleUserMapper;

    @Resource
    SysUserMapper sysUserMapper;

    @Resource
    SysLogMapper sysLogMapper;

    public void changeRoleAcls(Integer roleId, List<Integer> aclIdList) {
        //原角色ID的权限ID集合
        List<Integer> originAclIdList = sysRoleAclMapper.getAclIdListByRoleIdList(Lists.newArrayList(roleId));
        //原先权限集合与当前新的权限集合一样就不更新
        if (originAclIdList.size() == aclIdList.size()){
            Set<Integer> originAclIdSet = Sets.newHashSet(originAclIdList);
            Set<Integer> aclIdSet = Sets.newHashSet(aclIdList);
            originAclIdSet.removeAll(aclIdSet);
            if(CollectionUtils.isEmpty(originAclIdSet)) {
                return;
            }
        }
        updateRoleAcls(roleId, aclIdList);
        saveRoleAclLog(roleId, originAclIdList, aclIdList);
    }

    @Transactional
    public void updateRoleAcls(Integer roleId, List<Integer> aclIdList) {
        //删除原角色权限关联关系
        sysRoleAclMapper.deleteByRoleId(roleId);
        if(CollectionUtils.isEmpty(aclIdList)){
            return;
        }
        List<SysRoleAcl> roleAclList = Lists.newArrayList();
        for(Integer aclId : aclIdList) {
            SysRoleAcl sysRoleAcl = SysRoleAcl.builder().aclId(aclId).roleId(roleId).operator(RequestHolder.getCurrentUser().getUsername())
                    .operateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest())).operateTime(new Date()).build();
            roleAclList.add(sysRoleAcl);
        }
        sysRoleAclMapper.batchInsert(roleAclList);
    }

    public List<SysRole> getRoleListByAclId(Integer aclId) {
        List<Integer> roleIdList = sysRoleAclMapper.getRoleIdListByAclId(aclId);
        if(CollectionUtils.isEmpty(roleIdList)){
            return Lists.newArrayList();
        }
        return sysRoleMapper.getRoleListByIdList(roleIdList);
    }

    public List<SysUser> getUserListByAclId(Integer aclId) {
        List<SysRole> roleListByAclId = getRoleListByAclId(aclId);
        if(CollectionUtils.isEmpty(roleListByAclId)){
            return Lists.newArrayList();
        }
        List<Integer> roleIdList = roleListByAclId.stream().map(role -> role.getId()).collect(Collectors.toList());
        List<Integer> userIdList = sysRoleUserMapper.getUserIdListByRoleIdList(roleIdList);
        if(CollectionUtils.isEmpty(userIdList)){
            return Lists.newArrayList();
        }
        return sysUserMapper.getUserListByUserIdList(userIdList);
    }

    public void saveRoleAclLog(int roleId, List<Integer> before, List<Integer> after) {
        SysLogWithBLOBs log = new SysLogWithBLOBs();
        log.setType(LogType.TYPE_ROLE_ACL);
        log.setTargetId(roleId);
        log.setOldValue(before == null ? "" : JsonMapper.obj2String(before));
        log.setNewValue(after == null ? "" : JsonMapper.obj2String(after));
        log.setOperator(RequestHolder.getCurrentUser().getUsername());
        log.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        log.setOperateTime(new Date());
        log.setStatus(1);
        sysLogMapper.insertSelective(log);
    }
}
